﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;

using eBook.Core;
using eBook.Core.BusinessObjects;
using eBook.Core.Contracts;
using Brotherhood.HttpUtilities;
using HtmlAgilityPack;

namespace eBook.Services
{
  public class LCBookLookup : IBookLookup
  {
    public boBookInfo GetBookInfoByISBN(ISBN isbn)
    {      
      string permaLink = this.GetLCCNPermaLink(isbn);
      if ( string.IsNullOrEmpty(permaLink) )
        return null;

      string url = string.Format("{0}/mods", permaLink);
      var result = HttpAutomation.DoGet(url, "");

      return this.ParseBookInfo(result.Response);    
    }

    private boBookInfo ParseBookInfo(string response)
    {      
      XDocument xDoc = XDocument.Parse(response);
      XNamespace ns = xDoc.Root.GetDefaultNamespace();

      boBookInfo info = new boBookInfo() { InfoProvider = "LC" };      
      info.Title = (from x in xDoc.Descendants(ns + "title")
                    where !x.Parent.HasAttributes && x.Parent.Parent == xDoc.Root
                    select x.Value).FirstOrDefault();

      info.Subtitle = ( from x in xDoc.Descendants(ns + "subTitle")
                       where !x.Parent.HasAttributes && x.Parent.Parent == xDoc.Root
                       select x.Value).FirstOrDefault();

      info.PublisherName = ( from x in xDoc.Descendants(ns + "publisher")
                        select x.Value).FirstOrDefault();

      info.PublicationDate = ( from x in xDoc.Descendants(ns + "dateIssued")
                               where x.Attribute(ns + "encoding") != null && x.Attribute(ns + "encoding").Value == "marc"
                               select x.Value).FirstOrDefault();

      info.LCCN = ( from x in xDoc.Descendants(ns + "identifier")
                   where x.Attribute("type") != null && x.Attribute("type").Value == "lccn"
                   select x.Value).FirstOrDefault();

      info.Authors = ( from x in xDoc.Descendants(ns + "namePart")
                       where x.Parent.Attribute("type") != null && x.Parent.Attribute("type").Value == "personal"
                          && !x.HasAttributes
                          && x.Parent.Parent == xDoc.Root
                       select x.Value ).ToArray();


      info.DeweyDecimal = ( from x in xDoc.Descendants(ns + "classification")
                            where x.Attribute("authority") != null && x.Attribute("authority").Value == "ddc"
                            select x.Value ).FirstOrDefault();


      info.Topics = ( from x in xDoc.Descendants(ns + "topic")
                      select x.Value).ToArray();

      var links = ( from x in xDoc.Descendants(ns + "url")
                    where x.Parent.Parent == xDoc.Root
                      select x.Attribute("displayLabel") != null 
                                                         ? x.Attribute("displayLabel").Value + "|" + x.Value                   
                                                         : "|" + x.Value ).ToList();      
      links.Add(string.Format("LCCN permalink|http://lccn.loc.gov/{0}", info.LCCN));
      info.Links = links.ToArray();

      return info;
    }

    private string GetLCCNPermaLink(ISBN isbn)
    {
      string queryString = this.PrepareQueryString(isbn);
      //string url = string.Format("http://catalog.loc.gov/cgi-bin/Pwebrecon.cgi?{0}", queryString);
      string url = string.Format("http://catalog2.loc.gov/vwebv/search?{0}", queryString);

      var requestResult = HttpAutomation. DoGet(url, "");
      var page = requestResult.Response;

      string permalink = string.Empty;
      Match m = Regex.Match(page, "<a.*?id=\"permalink\".*?href=\"http://lccn.loc.gov/.*?\">(.*?)</a>");
      if (m.Success)
        permalink = m.Groups[1].Value;

      return permalink;
    }

    private string PrepareQueryString(ISBN isbn)
    {
      Dictionary<string, string> query = new Dictionary<string, string>();

      query.Add("searchArg", isbn.StrippedISBN);
      query.Add("searchCode", "GKEY%5E*");
      query.Add("searchType", "0");

      var w = ( from x in query select string.Format("{0}={1}", x.Key, x.Value) ).ToArray();
      string queryString = string.Join("&", w);

      return queryString;
    }


  }
}
